import random
import string
import django_redis
from captcha.image import ImageCaptcha # 生成图片验证码
from django.http import HttpResponse, JsonResponse
from django.views import View
import logging # 日志文件
from mg.utils.huyi_sms.sms3 import send_sms_code

logger = logging.getLogger('django') # 用Django的日志器

class ImgcodeView(View):
    def get(self,request,uuid):
        '''
        获取图片验证码资源
        :param request:
        :return:
        '''
        # 1.随机生成验证码（四位数值的类型）
        seed = string.digits # '0123456789'
        r = random.choices(seed,k=4) # ['7','2','4','5'] # 随机出来的数据
        imgcode_str = ''.join(r) # '7245' # 转化格式

        # 2.根据1生成数字创建的图片验证码资源
        imgcode = ImageCaptcha().generate(chars=imgcode_str)

        # 将imgcode_str存入redis数据库中
        redis_conn = django_redis.get_redis_connection('verify_code') # 建立数据库的连接，并选择连接哪一个
        # 第一个传的是key的值 第二传的是保存数据的时间（秒为单位） 第三传的是values的值
        # print(uuid)
        # print(imgcode_str)
        redis_conn.setex('img_%s'%uuid,300,imgcode_str)

        # 3.返回资源给前端
        # 第一个参数传的是内容，第二个传的是内容类型
        return HttpResponse(imgcode,content_type='image/png')

class SmscodeView(View):
    def get(self,request,phone):
        '''
        匹配并删除图形验证码
        :param request:
        :param phone:
        :return:
        '''
        # 1.获取请求参数（路径参数+查询字符串）
        imgcode_client = request.GET.get('imgcode','') # 获取图片验证码
        uuid = request.GET.get('uuid','') # 获取uuid

        # 2.校验参数（完整性判断）
        if not all([phone,imgcode_client,uuid]): # 只要这里有一个数据是不完整（没传的话，都会进行报错）
            return JsonResponse({
                'code':'4001',
                'errormsg':'缺少必传参数'
            })

        # 补充：避免用户频繁的发生发生短信验证码
        redis_conn = django_redis.get_redis_connection('verify_code') # 建立数据库的连接
        is_send = redis_conn.get('is_send_%s'%phone) # 获取is_send的值

        if is_send:
            return JsonResponse({
                'code':'4004',
                'errormsg':'发送短信验证码过于频繁'
            })

        # 3.获取服务器生成的图片验证码
        imgcode_server = redis_conn.get('img_%s'%uuid) # 获取图片验证码

        # 4.匹配（非空判断/一致性判断）
        if imgcode_server is None: # 判断数据是否为空
            return JsonResponse({
                'code':'4002',
                'errormsg':'图片验证码失效'
            })
        # 判断用户输入的验证码（lower转成小写）是否匹配服务器端的（他存到数据库是一个base的类型，所以要对他进行类型的转义并转成小写）
        if imgcode_client.lower() != imgcode_server.decode('utf-8').lower():
            return JsonResponse({
                'code':'4003',
                'errormsg':'图片验证码不一致'
            })

        # 5.删除图片验证码（避免用户恶意测试）
        try: # 可能途中会进行报错
            redis_conn.delete('img%s'%uuid) # 删除验证码
        except Exception as e:
            # 把错误记录到日志文件中
            logger.error(e)

        # 6.生成短信验证码（6位的数字）
        seed = string.digits # 获取0~9的字符串

        r = random.choices(seed,k=6) # 生成随机数（列表的形式）
        smscode_str = ''.join(r) # 转化成字符串
        print('验证码：',smscode_str)

        # 7.保存短信验证码到Redis数据库中
        # redis_conn.setex('sms_%s'%phone,60,smscode_str)
        # # 保存标志（用于判断是否可以发送短信），他的值是1
        # redis_conn.setex('is_send_%s'%phone,60,1)

        # 调用pipeline的管道
        pl = redis_conn.pipeline() # 调用管道
        pl.setex('sms_%s'%phone,60,smscode_str) # 保存短信验证码到Redis数据库中
        pl.setex('is_send_%s'%phone,60,1) # 保存标志（用于判断是否可以发送短信），他的值是1
        pl.execute() # 执行请求（批量执行）

        # 8.发送短信验证码（调用互亿天线的接口）
        ret = send_sms_code(smscode_str,phone)

        # 9.根据外部接口返回值响应前端结果
        # ret = {'code':'2'} # 模拟互亿天线返回的结果，用互亿天线的接口的话，把这个注释掉，打开上面的接口
        if ret.get('code') == 2:
            return JsonResponse({
                'code':'200',
                'msg':'OK'
            })
        return JsonResponse({
            'code':'5001',
            'errormsg':'发送短信验证码失败'
        })

class Check_SMScode(View):
    def get(self,request,phone):
        '''
        用户注册时短信验证码的校验功能
        :param request:
        :param phone:
        :return:
        '''
        # 接受请求参数
        smscode_client = request.GET.get('smscode','')
        # 校验参数
        if not all([phone,smscode_client]):
            return JsonResponse({
                'code':'4001',
                'errormsg':'缺少必传的参数'
            })
        # 查询服务器端短信验证码
        redis_conn = django_redis.get_redis_connection('verify_code')
        smscode_server = redis_conn.get('sms_%s'%phone) # 对redis数据库进行取值

        # 匹配（非空判断/有效性的判断）
        if smscode_server is None:
            return JsonResponse({
                'code':'4002',
                'errormsg':'短信验证码失效或者过期'
            })
        smscode_server = smscode_server.decode('utf-8')
        if smscode_client != smscode_server: # 那客户端的值和服务器的值进行匹配
            return JsonResponse({
                'code':'4003',
                'errormsg':'短信验证码不一致'
            })
        # 响应结果
        return JsonResponse({
            'code':'200',
            'msg':'OK'
        })







